package com.xingfly.web.api;

import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.xingfly.authentication.annotation.Authorization;
import com.xingfly.authentication.annotation.Me;
import com.xingfly.constant.ApiConstant;
import com.xingfly.constant.ErrorConstant;
import com.xingfly.constant.QiNiuConstant;
import com.xingfly.constant.HttpStatus;
import com.xingfly.error.TipException;
import com.xingfly.model.Image;
import com.xingfly.model.User;
import com.xingfly.model.vo.ImageVO;
import com.xingfly.service.ImageService;
import com.xingfly.service.QiNiuService;
import com.xingfly.web.model.ResponseModel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import java.io.IOException;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by SuperS on 24/05/2017.
 *
 * @author SuperS
 */
@Api(value = "images", description = "图片上传")
@RestController
@RequestMapping("/api/images")
public class ImageController {
    //七牛配置类
    Configuration configuration = new Configuration(Zone.zone0());
    //七牛文件上传管理对象
    UploadManager uploadManager = new UploadManager(configuration);
    @Autowired
    private ImageService imageService;
    @Autowired
    private QiNiuService qiNiuService;

    @ApiOperation(value = "图片上传", notes = "验证后上传图片")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "authorization", value = ApiConstant.AUTHORIZATION, paramType = "header", dataType = "String", required = true)
    })
    @PostMapping
    @Authorization
    @Transactional
    public ResponseModel create(@RequestParam(value = "files", required = false) MultipartFile[] files, @ApiIgnore @Me User me) throws TipException {
        //上传文件为空
        if (files==null){
            throw new TipException(ErrorConstant.ERROR_MSG_FILE_NOT_NULL, ErrorConstant.ERROR_CODE_FILE_NOT_NULL);
        }
        List<MultipartFile> list = Arrays.asList(files);
        List<ImageVO> images = new ArrayList<>();
        Long filesSize = 0L;
        if (list.isEmpty()) {
            throw new TipException(ErrorConstant.ERROR_MSG_FILE_NOT_NULL, ErrorConstant.ERROR_CODE_FILE_NOT_NULL);
        }
        //单个文件大小限制2MB
        for (MultipartFile file : list) {
            if (file.getSize() > QiNiuConstant.FILE_SIZE) {
                throw new TipException(ErrorConstant.ERROR_MSG_FILE_SIZE_ERROR, ErrorConstant.ERROR_CODE_FILE_SIZE_ERROR);
            }
            filesSize += file.getSize();
        }
        //所有文件大小限制20MB
        if (filesSize > QiNiuConstant.ALL_FILE_SIZE) {
            throw new TipException(ErrorConstant.ERROR_MSG_FILE_SIZE_ERROR, ErrorConstant.ERROR_CODE_FILE_SIZE_ERROR);
        }
        for (MultipartFile file : list) {
            if (file.isEmpty()) {
                continue;
            }
            String fileName = file.getOriginalFilename();
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            //限制图片文件类型
            if (!(suffixName.equals(".jpg") || suffixName.equals(".png") || suffixName.equals(".jpeg"))) {
                throw new TipException(ErrorConstant.ERROR_MSG_FILE_NOT_MATCH, ErrorConstant.ERROR_CODE_FILE_NOT_MATCH);
            }

            try {
                //获取认证
                Auth auth = qiNiuService.getToken(QiNiuConstant.AK, QiNiuConstant.SK);
                //创建Token
                String token = auth.uploadToken(QiNiuConstant.BUCKET);
                //获取日期时间用作上传图片名称
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
                //文件名称 用户ID_上传时间_随机值.文件格式
                String name = me.getId().toString() + "_" + sdf.format(new Date()) + "_" + UUID.randomUUID().toString() + suffixName;
                byte[] fileBytes = file.getBytes();
                //计算文件的MD5值
                String md5 = DigestUtils.md5DigestAsHex(fileBytes);
                Image image = imageService.findByHashTop1(md5);
                //如果此文件不存在
                if (image == null) {
                    //上传该文件
                    uploadManager.put(fileBytes, name, token);
                    String url = QiNiuConstant.DOMAIN + name;
                    Image save = new Image();
                    save.setUrl(url);
                    save.setUser(me);
                    save.setHash(md5);
                    save.setCreateTime(new Date());
                    Image saved = imageService.save(save);
                    images.add(ImageVO.toVO(saved));
                } else {
                    //如果存在找到该图片的url赋值给新创建的Image对象。
                    Image save = new Image();
                    save.setUrl(image.getUrl());
                    save.setUser(me);
                    save.setHash(md5);
                    save.setCreateTime(new Date());
                    Image saved = imageService.save(save);
                    images.add(ImageVO.toVO(saved));
                }
            } catch (UnknownHostException un) {
                throw new TipException(ErrorConstant.ERROR_MSG_FILE_UPLOAD_ERROR, ErrorConstant.ERROR_CODE_FILE_UPLOAD_ERROR);
            } catch (QiniuException qn) {
                throw new TipException(ErrorConstant.ERROR_MSG_FILE_UPLOAD_ERROR, ErrorConstant.ERROR_CODE_FILE_UPLOAD_ERROR);
            } catch (IOException io) {
                throw new TipException(ErrorConstant.ERROR_MSG_FILE_UPLOAD_ERROR, ErrorConstant.ERROR_CODE_FILE_UPLOAD_ERROR);
            }
        }
        return ResponseModel.builder().message(HttpStatus.STATUS_INFO_CREATED).code(HttpStatus.STATUS_CODE_SUCCESS).data(images).build();
    }
}
